const multer = require('multer');
const path = require('path');
const fs = require('fs-extra');
const crypto = require('crypto');
const db = require('../config/database');
const logger = require('../config/logger');

const UPLOAD_DIR = process.env.UPLOAD_DIR || path.join(__dirname, '../../uploads');
const CHUNK_DIR = path.join(UPLOAD_DIR, 'chunks');
const CHUNK_SIZE = parseInt(process.env.CHUNK_SIZE) || 5 * 1024 * 1024; // 5MB

// 确保目录存在
fs.ensureDirSync(CHUNK_DIR);
fs.ensureDirSync(UPLOAD_DIR);

// 配置multer存储 - 用于分片上传
// 🔥 修复：使用临时文件名，避免依赖 req.body（此时还未解析）
const chunkStorage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, CHUNK_DIR);
  },
  filename: (req, file, cb) => {
    // 使用临时唯一文件名，后续在 handleChunkUpload 中重命名
    const tempName = `temp_${Date.now()}_${Math.random().toString(36).substring(7)}`;
    cb(null, tempName);
  }
});

// 配置multer存储 - 用于单文件上传
const fileStorage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, UPLOAD_DIR);
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, uniqueSuffix + '-' + file.originalname);
  }
});

const upload = multer({
  storage: chunkStorage,
  limits: {
    fileSize: Infinity // 无限制
  },
  // 处理中文文件名
  fileFilter: (req, file, cb) => {
    // 修复中文文件名乱码
    file.originalname = Buffer.from(file.originalname, 'latin1').toString('utf8');
    cb(null, true);
  }
});

const uploadFile = multer({
  storage: fileStorage,
  limits: {
    fileSize: Infinity // 无限制
  },
  // 处理中文文件名
  fileFilter: (req, file, cb) => {
    // 修复中文文件名乱码
    file.originalname = Buffer.from(file.originalname, 'latin1').toString('utf8');
    cb(null, true);
  }
});

/**
 * Multer中间件 - 单文件上传
 */
exports.uploadFileMiddleware = uploadFile.single('file');

/**
 * 单文件上传处理器
 */
exports.uploadFile = async (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({
        success: false,
        message: '未接收到文件'
      });
    }

    let userId = req.user?.id || null;
    const { parentId, path: targetPath } = req.body;
    const file = req.file;

    // 验证用户ID（如果有）
    if (userId) {
      const [users] = await db.query('SELECT id FROM users WHERE id = ?', [userId]);
      if (users.length === 0) {
        logger.warn(`用户ID ${userId} 不存在，将设置为NULL`);
        userId = null;
      }
    }

    // 计算文件哈希
    const fileHash = await calculateFileMD5(file.path);

    // 检查文件是否已存在
    const [existingFiles] = await db.query(
      'SELECT * FROM files WHERE file_hash = ? AND is_deleted = 0',
      [fileHash]
    );

    if (existingFiles.length > 0) {
      // 文件已存在,删除临时文件
      await fs.remove(file.path);
      return res.json({
        success: true,
        message: '文件已存在',
        data: existingFiles[0]
      });
    }

    // 构建文件路径
    let filePath;
    let actualParentId = parentId || 0;

    if (targetPath) {
      // 如果提供了目标路径，使用目标路径
      filePath = targetPath;
      
      // 从路径查找或创建父目录ID
      const dirPath = path.dirname(targetPath);
      if (dirPath && dirPath !== '/' && dirPath !== '.') {
        const [parentDirs] = await db.query(
          'SELECT id FROM files WHERE file_path = ? AND is_directory = 1 AND is_deleted = 0',
          [dirPath]
        );
        if (parentDirs.length > 0) {
          actualParentId = parentDirs[0].id;
        }
      }
    } else if (actualParentId > 0) {
      // 使用parentId构建路径
      const [parent] = await db.query('SELECT file_path FROM files WHERE id = ?', [actualParentId]);
      if (parent.length > 0) {
        filePath = path.join(parent[0].file_path, file.originalname);
      } else {
        filePath = file.originalname;
      }
    } else {
      // 默认根目录
      filePath = `/${file.originalname}`;
    }

    // 确保路径以 / 开头
    if (!filePath.startsWith('/')) {
      filePath = '/' + filePath;
    }

    const finalPath = path.join(UPLOAD_DIR, filePath);
    await fs.ensureDir(path.dirname(finalPath));
    await fs.move(file.path, finalPath, { overwrite: true });

    const mimeType = getMimeType(file.originalname);

    // 插入文件记录
    const [result] = await db.query(
      `INSERT INTO files (file_name, file_path, file_size, file_hash, mime_type, user_id, parent_id, is_directory)
       VALUES (?, ?, ?, ?, ?, ?, ?, 0)`,
      [file.originalname, filePath, file.size, fileHash, mimeType, userId, actualParentId]
    );

    // 🔥 注释掉旧的传输任务记录（已改为客户端上传）
    // 传输任务现在由客户端在完成/失败时上传到 /api/transfer-queue/save
    // await db.query(
    //   `INSERT INTO transfer_tasks (user_id, file_id, file_name, file_path, file_size, transfer_type, status, transferred_size, started_at, completed_at)
    //    VALUES (?, ?, ?, ?, ?, 'upload', 'completed', ?, NOW(), NOW())`,
    //   [userId, result.insertId, file.originalname, filePath, file.size, file.size]
    // );

    logger.info(`文件上传成功: ${filePath}`);

    res.json({
      success: true,
      message: '文件上传成功',
      data: {
        fileId: result.insertId,
        fileName: file.originalname,
        filePath,
        fileSize: file.size
      }
    });
  } catch (error) {
    logger.error('文件上传失败:', error);
    
    // 清理可能存在的临时文件
    if (req.file && req.file.path) {
      try {
        await fs.remove(req.file.path);
      } catch (cleanupError) {
        logger.error('清理临时文件失败:', cleanupError);
      }
    }
    
    res.status(500).json({
      success: false,
      message: '文件上传失败: ' + error.message
    });
  }
};

/**
 * 上传分片 - 支持客户端格式
 */
exports.uploadChunk = (req, res, next) => {
  const uploadMiddleware = upload.single('file');
  uploadMiddleware(req, res, (err) => {
    if (err) {
      logger.error('分片上传Multer错误:', err);
      if (err instanceof multer.MulterError) {
        return res.status(400).json({
          success: false,
          message: `文件上传错误: ${err.message}，字段: ${err.field}`
        });
      }
      return res.status(500).json({
        success: false,
        message: `上传错误: ${err.message}`
      });
    }
    next();
  });
};

exports.handleChunkUpload = async (req, res) => {
  try {
    const { fileName, chunkIndex, totalChunks, parentPath, fileHash } = req.body;
    const userId = req.user.id;

    logger.info(`收到分片上传请求: fileName=${fileName}, chunkIndex=${chunkIndex}, totalChunks=${totalChunks}, fileHash=${fileHash}`);
    logger.info(`收到的字段:`, Object.keys(req.body));
    logger.info(`文件信息:`, req.file ? { fieldname: req.file.fieldname, originalname: req.file.originalname, size: req.file.size } : 'null');

    if (!req.file) {
      logger.error('未接收到文件分片，req.body:', req.body);
      return res.status(400).json({
        success: false,
        message: '未接收到文件分片'
      });
    }

    if (!fileName || chunkIndex === undefined || !totalChunks) {
      logger.error('缺少必需参数:', { fileName, chunkIndex, totalChunks });
      return res.status(400).json({
        success: false,
        message: '缺少必需参数: fileName, chunkIndex, totalChunks'
      });
    }

    // 使用客户端提供的fileHash作为标识符（如果提供），否则生成一个
    const fileIdentifier = fileHash || require('crypto').createHash('md5').update(`${userId}_${fileName}`).digest('hex');
    const chunkFileName = `${fileIdentifier}_chunk_${chunkIndex}`;
    
    logger.info(`使用文件标识符: ${fileIdentifier}`);
    
    // 🔥 重命名临时文件为正确的分片文件名
    const chunkPath = path.join(CHUNK_DIR, chunkFileName);
    await fs.move(req.file.path, chunkPath, { overwrite: true });
    
    logger.info(`分片文件已保存: ${chunkPath}`);

    logger.info(`分片上传成功: ${fileName} [${parseInt(chunkIndex) + 1}/${totalChunks}]`);

    // 检查是否所有分片都已上传
    const isLastChunk = parseInt(chunkIndex) === parseInt(totalChunks) - 1;
    
    if (isLastChunk) {
      // 最后一个分片，开始合并
      logger.info(`📦 所有分片已上传完成，开始合并文件: ${fileName}`);
      try {
        await mergeChunksSimple(fileIdentifier, fileName, totalChunks, parentPath, userId);
        
        logger.info(`✅ 文件合并成功: ${fileName}`);
        
        res.json({
          success: true,
          message: '文件上传成功',
          data: {
            uploadedCount: totalChunks,
            totalChunks,
            isComplete: true
          }
        });
      } catch (mergeError) {
        logger.error('❌ 合并分片失败:', mergeError);
        logger.error('错误堆栈:', mergeError.stack);
        res.status(500).json({
          success: false,
          message: '合并分片失败: ' + mergeError.message
        });
      }
    } else {
      res.json({
        success: true,
        message: '分片上传成功',
        data: {
          uploadedCount: parseInt(chunkIndex) + 1,
          totalChunks,
          isComplete: false
        }
      });
    }
  } catch (error) {
    logger.error('上传分片失败:', error);
    logger.error('错误堆栈:', error.stack);
    logger.error('请求体:', req.body);
    logger.error('文件信息:', req.file);
    res.status(500).json({
      success: false,
      message: '上传分片失败: ' + error.message
    });
  }
};

/**
 * 简化的分片合并函数
 */
async function mergeChunksSimple(fileIdentifier, fileName, totalChunks, parentPath, userId) {
  // 获取或创建父目录ID
  let parentId = 0;
  if (parentPath && parentPath !== '/') {
    // 检查父目录是否存在
    const [parentDirs] = await db.query(
      'SELECT id FROM files WHERE file_path = ? AND is_directory = 1 AND is_deleted = 0',
      [parentPath]
    );
    
    if (parentDirs.length > 0) {
      parentId = parentDirs[0].id;
    } else {
      // 父目录不存在，需要创建
      parentId = await createDirectoryRecursive(parentPath, userId);
    }
  }

  // 构建文件路径
  let filePath = fileName;
  if (parentPath && parentPath !== '/') {
    filePath = path.join(parentPath, fileName).replace(/\\/g, '/');
  } else {
    filePath = `/${fileName}`;
  }

  const finalPath = path.join(UPLOAD_DIR, filePath);
  await fs.ensureDir(path.dirname(finalPath));

  // 合并分片
  logger.info(`开始合并 ${totalChunks} 个分片到: ${finalPath}`);
  
  const writeStream = fs.createWriteStream(finalPath);
  
  for (let i = 0; i < totalChunks; i++) {
    const chunkFileName = `${fileIdentifier}_chunk_${i}`;
    const chunkPath = path.join(CHUNK_DIR, chunkFileName);
    
    if (await fs.pathExists(chunkPath)) {
      const data = await fs.readFile(chunkPath);
      writeStream.write(data);
      await fs.remove(chunkPath); // 删除临时分片
      
      if ((i + 1) % 100 === 0 || i === totalChunks - 1) {
        logger.info(`合并进度: ${i + 1}/${totalChunks}`);
      }
    } else {
      writeStream.end();
      logger.error(`分片 ${i} 不存在，路径: ${chunkPath}`);
      throw new Error(`分片 ${i} 不存在`);
    }
  }

  writeStream.end();

  await new Promise((resolve, reject) => {
    writeStream.on('finish', resolve);
    writeStream.on('error', reject);
  });
  
  logger.info(`分片合并完成，正在计算文件哈希...`);

  // 计算文件哈希
  const fileHash = await calculateFileMD5(finalPath);
  const stats = await fs.stat(finalPath);
  const mimeType = getMimeType(fileName);

  // 插入文件记录
  const [fileResult] = await db.query(
    `INSERT INTO files (file_name, file_path, file_size, file_hash, mime_type, user_id, parent_id, is_directory)
     VALUES (?, ?, ?, ?, ?, ?, ?, 0)`,
    [fileName, filePath, stats.size, fileHash, mimeType, userId, parentId]
  );

  // 🔥 注释掉旧的传输任务记录（已改为客户端上传）
  // await db.query(
  //   `INSERT INTO transfer_tasks (user_id, file_id, file_name, file_path, file_size, transfer_type, status, transferred_size, started_at, completed_at)
  //    VALUES (?, ?, ?, ?, ?, 'upload', 'completed', ?, NOW(), NOW())`,
  //   [userId, fileResult.insertId, fileName, filePath, stats.size, stats.size]
  // );

  logger.info(`文件合并完成: ${filePath}`);
}

/**
 * 检查文件上传状态
 */
exports.checkFileStatus = async (req, res) => {
  try {
    const { fileHash, fileName } = req.query;

    // 检查文件是否已存在
    const [existingFiles] = await db.query(
      'SELECT * FROM files WHERE file_hash = ? AND is_deleted = 0',
      [fileHash]
    );

    if (existingFiles.length > 0) {
      return res.json({
        success: true,
        data: {
          exists: true,
          shouldSkip: true,
          file: existingFiles[0]
        }
      });
    }

    // 检查是否有未完成的上传任务
    const [tasks] = await db.query(
      `SELECT t.*, GROUP_CONCAT(c.chunk_index) as uploaded_chunks
       FROM transfer_tasks t
       LEFT JOIN file_chunks c ON t.id = c.task_id AND c.is_uploaded = 1
       WHERE t.file_name = ? AND t.status IN ('pending', 'transferring', 'paused')
       AND t.user_id = ?
       GROUP BY t.id
       ORDER BY t.created_at DESC
       LIMIT 1`,
      [fileName, req.user.id]
    );

    if (tasks.length > 0) {
      const task = tasks[0];
      const uploadedChunks = task.uploaded_chunks ? task.uploaded_chunks.split(',').map(Number) : [];

      return res.json({
        success: true,
        data: {
          exists: false,
          hasTask: true,
          taskId: task.id,
          uploadedChunks,
          canResume: true
        }
      });
    }

    res.json({
      success: true,
      data: {
        exists: false,
        hasTask: false,
        canResume: false
      }
    });
  } catch (error) {
    logger.error('检查文件状态失败:', error);
    res.status(500).json({
      success: false,
      message: '检查文件状态失败'
    });
  }
};

/**
 * 创建上传任务
 * 🔥 此API已废弃 - 传输任务现在由客户端管理
 */
exports.createUploadTask = async (req, res) => {
  // 🔥 传输任务系统已更改：
  // - 传输中的任务：客户端内存 + JSON缓存
  // - 已完成/失败：客户端上传到 /api/transfer-queue/save
  // - 此API不再使用
  
  logger.warn('调用了已废弃的 createUploadTask API');
  
  res.status(410).json({
    success: false,
    message: '此API已废弃，传输任务现在由客户端管理',
    deprecated: true,
    alternative: '请使用 /api/transfer-queue/* API'
  });
  
  // 🔥 旧代码已注释
  // try {
  //   const { fileName, filePath, fileSize, fileHash, totalChunks, parentId = 0 } = req.body;
  //   const userId = req.user.id;
  //
  //   // 创建传输任务
  //   const [result] = await db.query(
  //     `INSERT INTO transfer_tasks (user_id, file_name, file_path, file_size, transfer_type, status, started_at)
  //      VALUES (?, ?, ?, ?, 'upload', 'pending', NOW())`,
  //     [userId, fileName, filePath, fileSize]
  //   );
  //
  //   const taskId = result.insertId;
  //
  //   // 创建分片记录
  //   const chunkRecords = [];
  //   for (let i = 0; i < totalChunks; i++) {
  //     chunkRecords.push([taskId, fileHash, i, '', 0, 0, null]);
  //   }
  //
  //   if (chunkRecords.length > 0) {
  //     await db.query(
  //       `INSERT INTO file_chunks (task_id, file_hash, chunk_index, chunk_hash, chunk_size, is_uploaded, uploaded_at)
  //        VALUES ?`,
  //       [chunkRecords]
  //     );
  //   }
  //
  //   logger.info(`创建上传任务: ${fileName} (${fileSize} bytes)`);
  //
  //   res.json({
  //     success: true,
  //     message: '任务创建成功',
  //     data: {
  //       taskId,
  //       parentId
  //     }
  //   });
  // } catch (error) {
  //   logger.error('创建上传任务失败:', error);
  //   res.status(500).json({
  //     success: false,
  //     message: '创建上传任务失败'
  //   });
  // }
};

/**
 * 合并文件分片
 */
exports.mergeChunks = async (req, res) => {
  try {
    const { taskId, fileHash, fileName, totalChunks, parentId, path: targetPath } = req.body;
    const userId = req.user.id;

    // 检查所有分片是否上传完成
    const [chunks] = await db.query(
      'SELECT * FROM file_chunks WHERE task_id = ? AND is_uploaded = 1 ORDER BY chunk_index',
      [taskId]
    );

    if (chunks.length !== totalChunks) {
      return res.status(400).json({
        success: false,
        message: `分片不完整: ${chunks.length}/${totalChunks}`
      });
    }

    // 构建文件路径
    let filePath;
    let actualParentId = parentId || 0;

    if (targetPath) {
      // 如果提供了目标路径，使用目标路径
      filePath = targetPath;
      
      // 从路径查找父目录ID
      const dirPath = path.dirname(targetPath);
      if (dirPath && dirPath !== '/' && dirPath !== '.') {
        const [parentDirs] = await db.query(
          'SELECT id FROM files WHERE file_path = ? AND is_directory = 1 AND is_deleted = 0',
          [dirPath]
        );
        if (parentDirs.length > 0) {
          actualParentId = parentDirs[0].id;
        }
      }
    } else if (actualParentId > 0) {
      // 使用parentId构建路径
      const [parent] = await db.query('SELECT file_path FROM files WHERE id = ?', [actualParentId]);
      if (parent.length > 0) {
        filePath = path.join(parent[0].file_path, fileName);
      } else {
        filePath = fileName;
      }
    } else {
      // 默认根目录
      filePath = `/${fileName}`;
    }

    // 确保路径以 / 开头
    if (!filePath.startsWith('/')) {
      filePath = '/' + filePath;
    }

    const finalPath = path.join(UPLOAD_DIR, filePath);
    await fs.ensureDir(path.dirname(finalPath));

    // 合并分片
    const writeStream = fs.createWriteStream(finalPath);

    for (const chunk of chunks) {
      const chunkPath = path.join(CHUNK_DIR, `${fileHash}_${chunk.chunk_index}`);
      if (await fs.pathExists(chunkPath)) {
        const data = await fs.readFile(chunkPath);
        writeStream.write(data);
        await fs.remove(chunkPath); // 删除临时分片
      }
    }

    writeStream.end();

    await new Promise((resolve, reject) => {
      writeStream.on('finish', resolve);
      writeStream.on('error', reject);
    });

    // 验证文件完整性
    const finalFileHash = await calculateFileMD5(finalPath);
    if (finalFileHash !== fileHash) {
      await fs.remove(finalPath);
      return res.status(400).json({
        success: false,
        message: '文件校验失败'
      });
    }

    // 获取文件信息
    const stats = await fs.stat(finalPath);
    const mimeType = getMimeType(fileName);

    // 插入文件记录
    const [fileResult] = await db.query(
      `INSERT INTO files (file_name, file_path, file_size, file_hash, mime_type, user_id, parent_id, is_directory)
       VALUES (?, ?, ?, ?, ?, ?, ?, 0)`,
      [fileName, filePath, stats.size, fileHash, mimeType, userId, actualParentId]
    );

    // 更新任务状态
    await db.query(
      `UPDATE transfer_tasks SET status = 'completed', file_id = ?, transferred_size = ?, completed_at = NOW()
       WHERE id = ?`,
      [fileResult.insertId, stats.size, taskId]
    );

    // 删除分片记录
    await db.query('DELETE FROM file_chunks WHERE task_id = ?', [taskId]);

    logger.info(`文件上传完成: ${filePath}`);

    res.json({
      success: true,
      message: '文件上传成功',
      data: {
        fileId: fileResult.insertId,
        fileName,
        filePath,
        fileSize: stats.size
      }
    });
  } catch (error) {
    logger.error('合并分片失败:', error);
    res.status(500).json({
      success: false,
      message: '合并分片失败'
    });
  }
};

/**
 * 计算文件MD5
 */
function calculateFileMD5(filePath) {
  return new Promise((resolve, reject) => {
    const hash = crypto.createHash('md5');
    const stream = fs.createReadStream(filePath);

    stream.on('data', data => hash.update(data));
    stream.on('end', () => resolve(hash.digest('hex')));
    stream.on('error', reject);
  });
}

/**
 * 递归创建目录
 */
async function createDirectoryRecursive(dirPath, userId) {
  const parts = dirPath.split('/').filter(p => p);
  let currentPath = '';
  let currentParentId = 0;

  for (const part of parts) {
    currentPath = currentPath ? `${currentPath}/${part}` : `/${part}`;
    
    // 检查目录是否已存在
    const [existing] = await db.query(
      'SELECT id FROM files WHERE file_path = ? AND is_directory = 1 AND is_deleted = 0',
      [currentPath]
    );

    if (existing.length > 0) {
      currentParentId = existing[0].id;
    } else {
      // 创建物理目录
      const fullPath = path.join(UPLOAD_DIR, currentPath);
      await fs.ensureDir(fullPath);

      // 插入数据库记录
      const [result] = await db.query(
        'INSERT INTO files (file_name, file_path, parent_id, is_directory, user_id) VALUES (?, ?, ?, 1, ?)',
        [part, currentPath, currentParentId, userId]
      );
      
      currentParentId = result.insertId;
      logger.info(`自动创建目录: ${currentPath}`);
    }
  }

  return currentParentId;
}

/**
 * 获取MIME类型
 */
function getMimeType(fileName) {
  const ext = path.extname(fileName).toLowerCase();
  const mimeTypes = {
    '.txt': 'text/plain',
    '.pdf': 'application/pdf',
    '.doc': 'application/msword',
    '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    '.xls': 'application/vnd.ms-excel',
    '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    '.jpg': 'image/jpeg',
    '.jpeg': 'image/jpeg',
    '.png': 'image/png',
    '.gif': 'image/gif',
    '.mp4': 'video/mp4',
    '.mp3': 'audio/mpeg',
    '.zip': 'application/zip',
    '.rar': 'application/x-rar-compressed'
  };

  return mimeTypes[ext] || 'application/octet-stream';
}
